home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / rcs55.zip / RCSFCMP.C < prev    next >
C/C++ Source or Header  |  1991-09-15  |  8KB  |  257 lines

  1. /*
  2.  *                     RCS file comparison
  3.  */
  4. /*****************************************************************************
  5.  *                       rcsfcmp()
  6.  *                       Testprogram: define FCMPTEST
  7.  *****************************************************************************
  8.  */
  9.  
  10. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  11.    Copyright 1990 by Paul Eggert
  12.    Distributed under license by the Free Software Foundation, Inc.
  13.  
  14. This file is part of RCS.
  15.  
  16. RCS is free software; you can redistribute it and/or modify
  17. it under the terms of the GNU General Public License as published by
  18. the Free Software Foundation; either version 1, or (at your option)
  19. any later version.
  20.  
  21. RCS is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. GNU General Public License for more details.
  25.  
  26. You should have received a copy of the GNU General Public License
  27. along with RCS; see the file COPYING.  If not, write to
  28. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30. Report problems and direct all questions to:
  31.  
  32.     rcs-bugs@cs.purdue.edu
  33.  
  34. */
  35.  
  36.  
  37.  
  38.  
  39.  
  40. /* $Log: rcsfcmp.c%v $
  41.  * Revision 1.2  1991/08/23  13:33:33  SGP
  42.  * Ported to MSDOS using Borland C++
  43.  *
  44.  * Revision 5.5  1990/11/27  09:26:05  eggert
  45.  * Fix comment leader bug.
  46.  *
  47.  * Revision 5.4  1990/11/01  05:03:42  eggert
  48.  * Permit arbitrary data in logs and comment leaders.
  49.  *
  50.  * Revision 5.3  1990/09/11  02:41:15  eggert
  51.  * Don't ignore differences inside keyword strings if -ko is set.
  52.  *
  53.  * Revision 5.1  1990/08/29  07:13:58  eggert
  54.  * Clean old log messages too.
  55.  *
  56.  * Revision 5.0  1990/08/22  08:12:49  eggert
  57.  * Don't append "checked in with -k by " log to logs,
  58.  * so that checking in a program with -k doesn't change it.
  59.  * Ansify and Posixate.  Remove lint.
  60.  *
  61.  * Revision 4.5  89/05/01  15:12:42  narten
  62.  * changed copyright header to reflect current distribution rules
  63.  * 
  64.  * Revision 4.4  88/08/09  19:12:50  eggert
  65.  * Shrink stdio code size.
  66.  * 
  67.  * Revision 4.3  87/12/18  11:40:02  narten
  68.  * lint cleanups (Guy Harris)
  69.  * 
  70.  * Revision 4.2  87/10/18  10:33:06  narten
  71.  * updting version number. Changes relative to 1.1 actually relative to 
  72.  * 4.1
  73.  * 
  74.  * Revision 1.2  87/03/27  14:22:19  jenkins
  75.  * Port to suns
  76.  * 
  77.  * Revision 4.1  83/05/10  16:24:04  wft
  78.  * Marker matching now uses trymatch(). Marker pattern is now
  79.  * checked precisely.
  80.  * 
  81.  * Revision 3.1  82/12/04  13:21:40  wft
  82.  * Initial revision.
  83.  *
  84.  */
  85.  
  86. /*
  87. #define FCMPTEST
  88. */
  89. /* Testprogram; prints out whether two files are identical,
  90.  * except for keywords
  91.  */
  92.  
  93. #include  "rcsbase.h"
  94.  
  95. libId(fcmpId, "$Id: rcsfcmp.c%v 1.2 1991/08/23 13:33:33 SGP Exp $")
  96.  
  97.  
  98.     int
  99. rcsfcmp(const char *xfname,
  100.         const char *uxfname,
  101.         const struct hshentry *delta)
  102. /* Function: compares the files xfname and uxfname. Returns true
  103.  * if xfname has the same contents as uxfname, while disregarding
  104.  * keyword values. For the LOG-keyword, rcsfcmp skips the log message
  105.  * given by the parameter delta in xfname. Thus, rcsfcmp returns true
  106.  * if xfname contains the same as uxfname, with the keywords expanded.
  107.  * Implementation: character-by-character comparison until $ is found.
  108.  * If a $ is found, read in the marker keywords; if they are real keywords
  109.  * and identical, read in keyword value. If value is terminated properly,
  110.  * disregard it and optionally skip log message; otherwise, compare value.
  111.  */
  112. {
  113.     register int xc,uxc;
  114.     char xkeyword[keylength+2],   uxkeyword[keylength+2];
  115.     int eqkeyvals;
  116.     register FILE * xfp, * uxfp;
  117.     register int delimiter;
  118.     register char * tp;
  119.     register const char *sp;
  120.     int result;
  121.     enum markers match1,match2;
  122.  
  123.     errno = 0;
  124.     if (!(xfp=fopen(sp=xfname,"r")) || !(errno=0, uxfp=fopen(sp=uxfname,"r"))) {
  125.        efaterror(sp);
  126.     }
  127.     result=false;
  128.     delimiter = Expand==OLD_EXPAND ? EOF : KDELIM;
  129.     xc=getc(xfp); uxc=getc(uxfp);
  130.     while( xc == uxc) { /* comparison loop */
  131.         if (xc==EOF) { /* finished; everything is the same*/
  132.             result=true;
  133.             break;
  134.         }
  135.     if (xc != delimiter) {
  136.             /* get the next characters */
  137.             xc=getc(xfp); uxc=getc(uxfp);
  138.         } else {
  139.             /* try to get both keywords */
  140.             tp = xkeyword;
  141.             while( (xc=getc(xfp))!=EOF && (tp< xkeyword+keylength) && (xc!='\n')
  142.                    && (xc!=KDELIM) && (xc!=VDELIM))
  143.                 *tp++ = xc;
  144.         *tp++ = xc;  /* add closing K/VDELIM */
  145.             *tp='\0';
  146.             tp = uxkeyword;
  147.             while( (uxc=getc(uxfp))!=EOF && (tp< uxkeyword+keylength) && (uxc!='\n')
  148.                    && (uxc!=KDELIM) && (uxc!=VDELIM))
  149.                 *tp++ = uxc;
  150.         *tp++ = xc;  /* add closing K/VDELIM */
  151.             *tp='\0';
  152.         /* Now we have 2 keywords, or something that looks like it. */
  153.         match1 = trymatch(xkeyword);
  154.         match2 = trymatch(uxkeyword);
  155.         if (match1 != match2) break; /* not identical */
  156. #ifdef FCMPTEST
  157.         VOID printf("found potential keywords %s and %s\n",xkeyword,uxkeyword);
  158. #endif
  159.  
  160.         if (match1 == Nomatch) {
  161.         /* not a keyword pattern, but could still be identical */
  162.         if (strcmp(xkeyword,uxkeyword)==0)
  163.              continue;
  164.         else break;
  165.         }
  166. #ifdef FCMPTEST
  167.         VOID printf("found common keyword %s\n",xkeyword);
  168. #endif
  169.         eqkeyvals = 1;
  170.         for (;;) {
  171.         if (xc==uxc) {
  172.             if (xc==KDELIM)
  173.             break;
  174.         } else {
  175.             eqkeyvals = 0;
  176.             if (xc==KDELIM) {
  177.             while (uxc!=KDELIM && uxc!='\n' && uxc!=EOF)
  178.                 uxc = getc(uxfp);
  179.             break;
  180.             }
  181.             if (uxc==KDELIM) {
  182.             while (xc!=KDELIM && xc!='\n' && xc!=EOF)
  183.                 xc = getc(xfp);
  184.             break;
  185.             }
  186.         }
  187.         if (xc=='\n' || uxc=='\n' || xc==EOF || uxc==EOF)
  188.             break;
  189.         xc = getc(xfp);
  190.         uxc = getc(uxfp);
  191.         }
  192.         if (xc!=uxc) break; /* not the same */
  193.         if (xc==KDELIM) {
  194.         xc=getc(xfp); uxc=getc(uxfp); /* skip closing KDELIM */
  195.         /* if the keyword is LOG, also skip the log message in xfp*/
  196.         if (match1==Log) {
  197.             /* first, compute the number of line feeds in log msg */
  198.             unsigned lncnt;
  199.             size_t ls, ccnt;
  200.             lncnt = 3;
  201.             sp = delta->log.string;
  202.             ls = delta->log.size;
  203.             if (sizeof(ciklog)-1<=ls && !strncmp(sp,ciklog,sizeof(ciklog)-1))
  204.             continue; /* this log message wasn't inserted */
  205.             while (ls--) if (*sp++=='\n') lncnt++;
  206.             while(xc!=EOF) {
  207.             if (xc=='\n')
  208.                 if(--lncnt==0) break;
  209.             xc=getc(xfp);
  210.             }
  211.             /* skip last comment leader */
  212.             /* Can't just skip another line here, because there may be */
  213.             /* additional characters on the line (after the Log....$)  */
  214.             for (ccnt=Comment.size; ccnt--; ) {
  215.             xc=getc(xfp);
  216.             if(xc=='\n') break;
  217.             /* reads to the end of the comment leader or '\n',     */
  218.             /* whatever comes first. This is because some editors  */
  219.             /* strip off trailing blanks from a leader like " * ". */
  220.             }
  221.         }
  222.         } else {
  223.         /* both end in the same character, but not a KDELIM */
  224.         /* must compare string values.*/
  225. #ifdef FCMPTEST
  226.         VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
  227. #endif
  228.         if (!eqkeyvals) break;
  229.             }
  230.         }
  231.     }
  232.     ffclose(xfp); ffclose(uxfp);
  233.     return result;
  234. }
  235.  
  236.  
  237.  
  238. #ifdef FCMPTEST
  239.  
  240. const char cmdid[] = "rcsfcmp";
  241.  
  242. main(int argc, char *argv[])
  243. /* first argument: comment leader; 2nd: log message, 3rd: expanded file,
  244.  * 4th: unexpanded file
  245.  */
  246. {       struct hshentry delta;
  247.  
  248.     Comment.string = argv[1];
  249.     Comment.size = strlen(argv[1]);
  250.     delta.log.string = argv[2];
  251.     delta.log.size = strlen(argv[2]);
  252.         if (rcsfcmp(argv[3],argv[4],&delta))
  253.                 VOID printf("files are the same\n");
  254.         else    VOID printf("files are different\n");
  255. }
  256. #endif
  257.